package cn.ztf.zshop.security.admin.config;

import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.StopMatchException;
import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.router.SaHttpMethod;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.session.SaSessionCustomUtil;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import cn.ztf.zshop.security.admin.constant.SaSessionCacheKey;
import cn.ztf.zshop.security.admin.constant.SaSessionName;
import cn.ztf.zshop.security.admin.dto.PermissionDto;
import cn.ztf.zshop.security.admin.service.SecurityService;
import cn.ztf.zshop.security.admin.service.SysUserSecurityService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;

@Slf4j
@Configuration
public class SaTokenConfigure implements WebMvcConfigurer {

    @Autowired
    private SysUserSecurityService sysUserSecurityService;

    @Value("${admin_id}")
    private String adminId;
    @Autowired
    public void checkAdmin(){
        if (StringUtils.hasLength(adminId)){
            log.info("=========超级管理员id配置成功,admin_id:{}=================",adminId);
        }else {
            log.error("=========超级管理员id未配置,请在配置文件中配置admin_id=================");
        }
    }

    private final List<String> excludePaths = Arrays.asList(
            "/sys/user/login",
            "/sys/user/logout",
            "/captcha/get",
            "/captcha/check");

    // 注册拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new SaInterceptor(handle -> {
                     //excludePaths 排除路径
                    SaRouter.match(excludePaths).stop();
                    // 校验登录
                    StpUtil.checkLogin();
                    // 校验超级管理员
                    checkRoot();
                    // 动态权限校验
                    SaSession saSession = SaSessionCustomUtil.getSessionById(SaSessionName.PERMISSIONS);
                    List<PermissionDto> permissionDtoList =  saSession.get(SaSessionCacheKey.PERMISSION_all_CACHE_KEY, () -> {
                        //缓存没有则 从数据库查询系统的全部权限
                        return sysUserSecurityService.findAllPermission();
                    });
                    for (PermissionDto permissionDto : permissionDtoList) {
                        SaRouter.match(SaHttpMethod.toEnum(permissionDto.getMethod()))
                                .match(permissionDto.getUrl(),()-> StpUtil.checkPermissionAnd(permissionDto.getPermission()))
                                .stop();
                    }
                }))
                .addPathPatterns("/**");
    }



    private void checkRoot(){
        String id = StpUtil.getLoginIdAsString();
        if (id.equals(adminId)){
            // 如果是超级管理员则直接放行
            throw new StopMatchException();
        }
    }

}
